home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-11  |  16.8 KB  |  678 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Guido van Rossum.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36. #include "config.h"
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. static char sccsid[] = "@(#)glob.c    5.12 (Berkeley) 6/24/91";
  39. #endif /* LIBC_SCCS and not lint */
  40. /*
  41.  * Glob: the interface is a superset of the one defined in POSIX 1003.2,
  42.  * draft 9.
  43.  *
  44.  * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
  45.  *
  46.  * Optional extra services, controlled by flags not defined by POSIX:
  47.  *
  48.  * GLOB_QUOTE:
  49.  *    Escaping convention: \ inhibits any special meaning the following
  50.  *    character might have (except \ at end of string is retained).
  51.  * GLOB_MAGCHAR:
  52.  *    Set in gl_flags if pattern contained a globbing character.
  53.  * GLOB_ALTNOT:
  54.  *    Use ^ instead of ! for "not".
  55.  * gl_matchc:
  56.  *    Number of matches in the current invocation of glob.
  57.  */
  58.  
  59. #ifdef notdef
  60. #include <sys/types.h>
  61. #include <sys/param.h>
  62. #include <sys/stat.h>
  63. #include <dirent.h>
  64. #include <ctype.h>
  65. typedef void * ptr_t;
  66. #endif
  67.  
  68. #define Char __Char
  69. #include "sh.h"
  70. #undef Char
  71. #undef QUOTE
  72. #undef TILDE
  73. #undef META
  74. #undef CHAR
  75. #undef ismeta
  76. #undef Strchr
  77.  
  78. #include <glob.h>
  79.  
  80. #ifndef S_ISDIR
  81. #define S_ISDIR(a)    (((a) & S_IFMT) == S_IFDIR)
  82. #endif
  83.  
  84. #if !defined(S_ISLNK) && defined(S_IFLNK)
  85. #define S_ISLNK(a)    (((a) & S_IFMT) == S_IFLNK)
  86. #endif
  87.  
  88. #if !defined(S_ISLNK) && !defined(lstat)
  89. #define lstat stat
  90. #endif
  91.  
  92. typedef unsigned short Char;
  93.  
  94. static    int     glob1         __P((Char *, glob_t *, int));
  95. static    int     glob2        __P((Char *, Char *, Char *, glob_t *, int));
  96. static    int     glob3        __P((Char *, Char *, Char *, Char *,
  97.                      glob_t *, int));
  98. static    int     globextend    __P((Char *, glob_t *));
  99. static    int     match        __P((Char *, Char *, Char *, int));
  100. static    int     compare    __P((const ptr_t, const ptr_t));
  101. static     DIR    *Opendir    __P((Char *));
  102. #ifdef S_IFLNK
  103. static    int     Lstat        __P((Char *, struct stat *));
  104. #endif
  105. static     Char     *Strchr        __P((Char *, int));
  106. #ifdef DEBUG
  107. static    void     qprintf    __P((Char *));
  108. #endif
  109.  
  110. #define    DOLLAR        '$'
  111. #define    DOT        '.'
  112. #define    EOS        '\0'
  113. #define    LBRACKET    '['
  114. #define    NOT        '!'
  115. #define ALTNOT        '^'
  116. #define    QUESTION    '?'
  117. #ifdef ALTESC
  118. #define    QUOTE        escchar
  119. #else
  120. #define QUOTE        '\\'
  121. #endif
  122. #define    RANGE        '-'
  123. #define    RBRACKET    ']'
  124. #define    SEP        '/'
  125. #if defined(__MINT__) && defined(ALTESC)
  126. #define SEP2        '\\'
  127. #endif
  128. #define    STAR        '*'
  129. #define    TILDE        '~'
  130. #define    UNDERSCORE    '_'
  131.  
  132. #define    M_META        0x8000
  133. #define M_PROTECT    0x4000
  134. #define    M_MASK        0xffff
  135. #define    M_ASCII        0x00ff
  136.  
  137. #define    CHAR(c)        ((c)&M_ASCII)
  138. #define    META(c)        ((c)|M_META)
  139. #define    M_ALL        META('*')
  140. #define    M_END        META(']')
  141. #define    M_NOT        META('!')
  142. #define    M_ALTNOT    META('^')
  143. #define    M_ONE        META('?')
  144. #define    M_RNG        META('-')
  145. #define    M_SET        META('[')
  146. #define    ismeta(c)    (((c)&M_META) != 0)
  147.  
  148. /*
  149.  * Need to dodge two kernel bugs:
  150.  * opendir("") != opendir(".")
  151.  * NAMEI_BUG: on plain files trailing slashes are ignored in some kernels.
  152.  *            POSIX specifies that they should be ignored in directories.
  153.  */
  154.  
  155. static DIR *
  156. Opendir(str)
  157.     register Char *str;
  158. {
  159.     char    buf[MAXPATHLEN];
  160.     register char *dc = buf;
  161.  
  162.     if (!*str)
  163.     return (opendir("."));
  164.     while (*dc++ = *str++);
  165.     return (opendir(buf));
  166. }
  167.  
  168. #ifdef S_IFLNK
  169. static int
  170. Lstat(fn, sb)
  171.     register Char *fn;
  172.     struct stat *sb;
  173. {
  174.     char    buf[MAXPATHLEN];
  175.     register char *dc = buf;
  176.  
  177.     while (*dc++ = *fn++);
  178. # ifdef NAMEI_BUG
  179.     {
  180.     int     st;
  181.  
  182.     st = lstat(buf, sb);
  183.     if (*buf)
  184.         dc--;
  185.     return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
  186.     }
  187. # else
  188.     return (lstat(buf, sb));
  189. # endif    /* NAMEI_BUG */
  190. }
  191. #else
  192. #define Lstat Stat
  193. #endif /* S_IFLNK */
  194.  
  195. static int
  196. Stat(fn, sb)
  197.     register Char *fn;
  198.     struct stat *sb;
  199. {
  200.     char    buf[MAXPATHLEN];
  201.     register char *dc = buf;
  202.  
  203.     while (*dc++ = *fn++);
  204. #ifdef NAMEI_BUG
  205.     {
  206.     int     st;
  207.  
  208.     st = lstat(buf, sb);
  209.     if (*buf)
  210.         dc--;
  211.     return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
  212.     }
  213. #else
  214.     return (stat(buf, sb));
  215. #endif /* NAMEI_BUG */
  216. }
  217.  
  218. static Char *
  219. Strchr(str, ch)
  220.     Char *str;
  221.     int ch;
  222. {
  223.     do
  224.     if (*str == ch)
  225.         return (str);
  226.     while (*str++);
  227.     return (NULL);
  228. }
  229.  
  230. #ifdef DEBUG
  231. static void
  232. qprintf(s)
  233. Char *s;
  234. {
  235.     Char *p;
  236.  
  237.     for (p = s; *p; p++)
  238.     printf("%c", *p & 0xff);
  239.     printf("\n");
  240.     for (p = s; *p; p++)
  241.     printf("%c", *p & M_PROTECT ? '"' : ' ');
  242.     printf("\n");
  243.     for (p = s; *p; p++)
  244.     printf("%c", *p & M_META ? '_' : ' ');
  245.     printf("\n");
  246. }
  247. #endif /* DEBUG */
  248.  
  249. static int
  250. compare(p, q)
  251.     const ptr_t  p, q;
  252. {
  253.     return (strcmp(*(char **) p, *(char **) q));
  254. }
  255.  
  256. /*
  257.  * The main glob() routine: compiles the pattern (optionally processing
  258.  * quotes), calls glob1() to do the real pattern matching, and finally
  259.  * sorts the list (unless unsorted operation is requested).  Returns 0
  260.  * if things went well, nonzero if errors occurred.  It is not an error
  261.  * to find no matches.
  262.  */
  263. int
  264. glob(pattern, flags, errfunc, pglob)
  265.     const char *pattern;
  266.     int     flags;
  267.     int     (*errfunc) __P((char *, int));
  268.     glob_t *pglob;
  269. {
  270.     int     err, oldpathc;
  271.     Char *bufnext, *bufend, *compilebuf, m_not;
  272.     const unsigned char *compilepat, *patnext;
  273.     int     c, not;
  274.     Char patbuf[MAXPATHLEN + 1], *qpatnext;
  275.     int     no_match;
  276.  
  277.     patnext = (unsigned char *) pattern;
  278.     if (!(flags & GLOB_APPEND)) {
  279.     pglob->gl_pathc = 0;
  280.     pglob->gl_pathv = NULL;
  281.     if (!(flags & GLOB_DOOFFS))
  282.         pglob->gl_offs = 0;
  283.     }
  284.     pglob->gl_flags = flags & ~GLOB_MAGCHAR;
  285.     pglob->gl_errfunc = errfunc;
  286.     oldpathc = pglob->gl_pathc;
  287.     pglob->gl_matchc = 0;
  288.  
  289.     if (pglob->gl_flags & GLOB_ALTNOT) {
  290.     not = ALTNOT;
  291.     m_not = M_ALTNOT;
  292.     }
  293.     else {
  294.     not = NOT;
  295.     m_not = M_NOT;
  296.     }
  297.  
  298.     bufnext = patbuf;
  299.     bufend = bufnext + MAXPATHLEN;
  300.     compilebuf = bufnext;
  301.     compilepat = patnext;
  302.  
  303.     no_match = *patnext == not;
  304.     if (no_match)
  305.     patnext++;
  306.  
  307.     if (flags & GLOB_QUOTE) {
  308.     /* Protect the quoted characters */
  309.     while (bufnext < bufend && (c = *patnext++) != EOS) 
  310.         if (c == QUOTE) {
  311.         if ((c = *patnext++) == EOS) {
  312.             c = QUOTE;
  313.             --patnext;
  314.         }
  315.         *bufnext++ = c | M_PROTECT;
  316.         }
  317.         else
  318.         *bufnext++ = c;
  319.     }
  320.     else 
  321.     while (bufnext < bufend && (c = *patnext++) != EOS) 
  322.         *bufnext++ = c;
  323.     *bufnext = EOS;
  324.  
  325.     bufnext = patbuf;
  326.     qpatnext = patbuf;
  327.     /* we don't need to check for buffer overflow any more */
  328.     while ((c = *qpatnext++) != EOS) {
  329.     switch (c) {
  330.     case LBRACKET:
  331.         c = *qpatnext;
  332.         if (c == not)
  333.         ++qpatnext;
  334.         if (*qpatnext == EOS ||
  335.         Strchr(qpatnext + 1, RBRACKET) == NULL) {
  336.         *bufnext++ = LBRACKET;
  337.         if (c == not)
  338.             --qpatnext;
  339.         break;
  340.         }
  341.         pglob->gl_flags |= GLOB_MAGCHAR;
  342.         *bufnext++ = M_SET;
  343.         if (c == not)
  344.         *bufnext++ = m_not;
  345.         c = *qpatnext++;
  346.         do {
  347.         *bufnext++ = CHAR(c);
  348.         if (*qpatnext == RANGE &&
  349.             (c = qpatnext[1]) != RBRACKET) {
  350.             *bufnext++ = M_RNG;
  351.             *bufnext++ = CHAR(c);
  352.             qpatnext += 2;
  353.         }
  354.         } while ((c = *qpatnext++) != RBRACKET);
  355.         *bufnext++ = M_END;
  356.         break;
  357.     case QUESTION:
  358.         pglob->gl_flags |= GLOB_MAGCHAR;
  359.         *bufnext++ = M_ONE;
  360.         break;
  361.     case STAR:
  362.         pglob->gl_flags |= GLOB_MAGCHAR;
  363.         *bufnext++ = M_ALL;
  364.         break;
  365.     default:
  366.         *bufnext++ = CHAR(c);
  367.         break;
  368.     }
  369.     }
  370.     *bufnext = EOS;
  371. #ifdef DEBUG
  372.     qprintf(patbuf);
  373. #endif
  374.  
  375.     if ((err = glob1(patbuf, pglob, no_match)) != 0)
  376.     return (err);
  377.  
  378.     /*
  379.      * If there was no match we are going to append the pattern 
  380.      * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
  381.      * and the pattern did not contain any magic characters
  382.      * GLOB_NOMAGIC is there just for compatibility with csh.
  383.      */
  384.     if (pglob->gl_pathc == oldpathc && 
  385.     ((flags & GLOB_NOCHECK) || 
  386.      ((flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) {
  387.     if (!(flags & GLOB_QUOTE)) {
  388.         Char *dp = compilebuf;
  389.         const unsigned char *sp = compilepat;
  390.  
  391.         while (*dp++ = *sp++);
  392.     }
  393.     else {
  394.         /*
  395.          * copy pattern, interpreting quotes; this is slightly different
  396.          * than the interpretation of quotes above -- which should prevail?
  397.          */
  398.         while (*compilepat != EOS) {
  399.         if (*compilepat == QUOTE) {
  400.             if (*++compilepat == EOS)
  401.             --compilepat;
  402.         }
  403.         *compilebuf++ = (unsigned char) *compilepat++;
  404.         }
  405.         *compilebuf = EOS;
  406.     }
  407.     return (globextend(patbuf, pglob));
  408.     }
  409.     else if (!(flags & GLOB_NOSORT))
  410.     qsort((char *) (pglob->gl_pathv + pglob->gl_offs + oldpathc),
  411.           pglob->gl_pathc - oldpathc, sizeof(char *),
  412.           (int (*) __P((const void *, const void *))) compare);
  413.     return (0);
  414. }
  415.  
  416. static int
  417. glob1(pattern, pglob, no_match)
  418.     Char *pattern;
  419.     glob_t *pglob;
  420.     int     no_match;
  421. {
  422.     Char pathbuf[MAXPATHLEN + 1];
  423.  
  424.     /*
  425.      * a null pathname is invalid -- POSIX 1003.1 sect. 2.4.
  426.      */
  427.     if (*pattern == EOS)
  428.     return (0);
  429.     return (glob2(pathbuf, pathbuf, pattern, pglob, no_match));
  430. }
  431.  
  432. /*
  433.  * functions glob2 and glob3 are mutually recursive; there is one level
  434.  * of recursion for each segment in the pattern that contains one or
  435.  * more meta characters.
  436.  */
  437. static int
  438. glob2(pathbuf, pathend, pattern, pglob, no_match)
  439.     Char *pathbuf, *pathend, *pattern;
  440.     glob_t *pglob;
  441.     int     no_match;
  442. {
  443.     struct stat sbuf;
  444.     int anymeta;
  445.     Char *p, *q;
  446.  
  447.     /*
  448.      * loop over pattern segments until end of pattern or until segment with
  449.      * meta character found.
  450.      */
  451.     anymeta = 0;
  452.     for (;;) {
  453.     if (*pattern == EOS) {    /* end of pattern? */
  454.         *pathend = EOS;
  455.         if (Lstat(pathbuf, &sbuf))
  456.         return (0);
  457.  
  458.         if (((pglob->gl_flags & GLOB_MARK) &&
  459. #if defined(__MINT__) && defined(ALTESC)
  460.          (pathend[-1] != SEP2 || escchar == SEP2) &&
  461. #endif
  462.          pathend[-1] != SEP) &&
  463.         (S_ISDIR(sbuf.st_mode)
  464. #ifdef S_IFLNK
  465.          || (S_ISLNK(sbuf.st_mode) &&
  466.              (Stat(pathbuf, &sbuf) == 0) &&
  467.              S_ISDIR(sbuf.st_mode))
  468. #endif
  469.          )) {
  470.         *pathend++ = SEP;
  471.         *pathend = EOS;
  472.         }
  473.         ++pglob->gl_matchc;
  474.         return (globextend(pathbuf, pglob));
  475.     }
  476.  
  477.     /* find end of next segment, copy tentatively to pathend */
  478.     q = pathend;
  479.     p = pattern;
  480. #if defined(__MINT__) && defined(ALTESC)
  481.     while (*p != EOS && *p != SEP && (*p != SEP2 || escchar == SEP2)) {
  482. #else
  483.     while (*p != EOS && *p != SEP) {
  484. #endif
  485.         if (ismeta(*p))
  486.         anymeta = 1;
  487.         *q++ = *p++;
  488.     }
  489.  
  490.     if (!anymeta) {        /* no expansion, do next segment */
  491.         pathend = q;
  492.         pattern = p;
  493. #if defined(__MINT__) && defined(ALTESC)
  494.         while (*pattern == SEP || (escchar != SEP2 && *pattern == SEP2))
  495. #else
  496.         while (*pattern == SEP)
  497. #endif
  498.         *pathend++ = *pattern++;
  499.     }
  500.     else            /* need expansion, recurse */
  501.         return (glob3(pathbuf, pathend, pattern, p, pglob, no_match));
  502.     }
  503.     /* NOTREACHED */
  504. }
  505.  
  506.  
  507. static int
  508. glob3(pathbuf, pathend, pattern, restpattern, pglob, no_match)
  509.     Char *pathbuf, *pathend, *pattern, *restpattern;
  510.     glob_t *pglob;
  511.     int     no_match;
  512. {
  513.     extern int errno;
  514.     DIR    *dirp;
  515.     struct dirent *dp;
  516.     int     err;
  517.     Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT;
  518.  
  519.     *pathend = EOS;
  520.     errno = 0;
  521.  
  522.     if (!(dirp = Opendir(pathbuf)))
  523.     /* todo: don't call for ENOENT or ENOTDIR? */
  524.     if (pglob->gl_errfunc &&
  525.         (*pglob->gl_errfunc) (pathbuf, errno) ||
  526.         (pglob->gl_flags & GLOB_ERR))
  527.         return (GLOB_ABEND);
  528.     else
  529.         return (0);
  530.  
  531.     err = 0;
  532.  
  533.     /* search directory for matching names */
  534.     while ((dp = readdir(dirp))) {
  535.     register unsigned char *sc;
  536.     register Char *dc;
  537.  
  538.     /* initial DOT must be matched literally */
  539.     if (dp->d_name[0] == DOT && *pattern != DOT)
  540.         continue;
  541.     for (sc = (unsigned char *) dp->d_name, dc = pathend; *dc++ = *sc++;);
  542.     if (match(pathend, pattern, restpattern, m_not) == no_match) {
  543.         *pathend = EOS;
  544.         continue;
  545.     }
  546.     err = glob2(pathbuf, --dc, restpattern, pglob, no_match);
  547.     if (err)
  548.         break;
  549.     }
  550.     /* todo: check error from readdir? */
  551.     (void) closedir(dirp);
  552.     return (err);
  553. }
  554.  
  555.  
  556. /*
  557.  * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
  558.  * add the new item, and update gl_pathc.
  559.  *
  560.  * This assumes the BSD realloc, which only copies the block when its size
  561.  * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
  562.  * behavior.
  563.  *
  564.  * Return 0 if new item added, error code if memory couldn't be allocated.
  565.  *
  566.  * Invariant of the glob_t structure:
  567.  *    Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
  568.  *     gl_pathv points to (gl_offs + gl_pathc + 1) items.
  569.  */
  570. static int
  571. globextend(path, pglob)
  572.     Char *path;
  573.     glob_t *pglob;
  574. {
  575.     register char **pathv;
  576.     register int i;
  577.     unsigned int newsize;
  578.     char   *copy;
  579.     Char *p;
  580.  
  581.     newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
  582.     pathv = (char **) (pglob->gl_pathv ?
  583.                realloc((ptr_t) pglob->gl_pathv, newsize) :
  584.                malloc((size_t) newsize));
  585.     if (pathv == NULL)
  586.     return (GLOB_NOSPACE);
  587.  
  588.     if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
  589.     /* first time around -- clear initial gl_offs items */
  590.     pathv += pglob->gl_offs;
  591.     for (i = pglob->gl_offs; --i >= 0;)
  592.         *--pathv = NULL;
  593.     }
  594.     pglob->gl_pathv = pathv;
  595.  
  596.     for (p = path; *p++;);
  597.     if ((copy = (char *) malloc((size_t) (p - path))) != NULL) {
  598.     register char *dc = copy;
  599.     register Char *sc = path;
  600.  
  601.     while (*dc++ = *sc++);
  602.     pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
  603.     }
  604.     pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
  605.     return ((copy == NULL) ? GLOB_NOSPACE : 0);
  606. }
  607.  
  608.  
  609. /*
  610.  * pattern matching function for filenames.  Each occurrence of the *
  611.  * pattern causes a recursion level.
  612.  */
  613. static  int
  614. match(name, pat, patend, m_not)
  615.     register Char *name, *pat, *patend;
  616.     int m_not;
  617. {
  618.     int ok, negate_range;
  619.     Char c, k;
  620.  
  621.     while (pat < patend) {
  622.     c = *pat++;
  623.     switch (c & M_MASK) {
  624.     case M_ALL:
  625.         if (pat == patend)
  626.         return (1);
  627.         for (; *name != EOS; ++name) {
  628.         if (match(name, pat, patend, m_not))
  629.             return (1);
  630.         }
  631.         return (0);
  632.     case M_ONE:
  633.         if (*name++ == EOS)
  634.         return (0);
  635.         break;
  636.     case M_SET:
  637.         ok = 0;
  638.         k = *name++;
  639.         if (negate_range = ((*pat & M_MASK) == m_not))
  640.         ++pat;
  641.         while (((c = *pat++) & M_MASK) != M_END) {
  642.         if ((*pat & M_MASK) == M_RNG) {
  643.             if (c <= k && k <= pat[1])
  644.             ok = 1;
  645.             pat += 2;
  646.         }
  647.         else if (c == k)
  648.             ok = 1;
  649.         }
  650.         if (ok == negate_range)
  651.         return (0);
  652.         break;
  653.     default:
  654.         if (*name++ != c)
  655.         return (0);
  656.         break;
  657.     }
  658.     }
  659.     return (*name == EOS);
  660. }
  661.  
  662. /* free allocated data belonging to a glob_t structure */
  663. void
  664. globfree(pglob)
  665.     glob_t *pglob;
  666. {
  667.     register int i;
  668.     register char **pp;
  669.  
  670.     if (pglob->gl_pathv != NULL) {
  671.     pp = pglob->gl_pathv + pglob->gl_offs;
  672.     for (i = pglob->gl_pathc; i--; ++pp)
  673.         if (*pp)
  674.         free((ptr_t) *pp), *pp = NULL;
  675.     free((ptr_t) pglob->gl_pathv), pglob->gl_pathv = NULL;
  676.     }
  677. }
  678.